Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't package private library and typelib files separately. #456

Merged
merged 3 commits into from
Aug 13, 2024

Conversation

mtwebster
Copy link
Member

@mtwebster mtwebster commented Jul 24, 2024

The cinnamon-screensaver package is already arch-specific, and libcscreensaver isn't used outside of this package.

The libcscreensaver0 package will remain as an empty transitional package.

ref:
linuxmint/cinnamon#11999
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1059341#15

@mtwebster
Copy link
Member Author

@Fantu look ok to you?

Thanks

@mtwebster mtwebster requested a review from clefebvre July 24, 2024 16:56
@Fantu
Copy link
Contributor

Fantu commented Jul 24, 2024

Big thanks, from a fast look ok the move from shared to private and can make possible remove another difference from Debian packaging (done to solve policy issue for shared library).
I think that libcscreensaver0 can be removed, adding it to Breaks: of cinnamon-screensaver will be no needs of empty "transition package".
Looking debian folder seems will be good a deep check and possible improvements as not done in latest years.
For example, from a fast look I saw that d/cinnamon-screensaver-pam-helper.install should be removed (was missed in older changes) and I think there are other improvements from Debian packaging will be useful like these:
https://salsa.debian.org/cinnamon-team/cinnamon-screensaver/-/commit/7e5befb63b0f167198955566de2e426918a19f28
https://salsa.debian.org/cinnamon-team/cinnamon-screensaver/-/commit/7f176749620f87eb5e01aa454667379ee5714632

@Fantu
Copy link
Contributor

Fantu commented Jul 27, 2024

I tested it and found that fails on:

gi.require_version('CScreensaver', '1.0')

I did a fast search and tried GIRepository.Repository.prepend_library_path (after saw https://stackoverflow.com/questions/42631816/modify-gobject-load-library-path-for-python) but didn't work.

include_directories: inc,
cpp_args: '-DG_LOG_DOMAIN="CScreensaver"',
dependencies: libcscreensaver_deps,
install_dir: libexecdir,
Copy link

@smcv smcv Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be better to build with --libexecdir=libexec in debian/rules, and change cinnamon-screensaver-pam-helper, cs-backup-locker, girepository-1.0/CScreensaver-1.0.typelib and libcscreensaver.so so they're installed into libexecdir / 'cinnamon-screensaver' (and then adjust paths in debian/*.install appropriately).

The install_rpath would also need to be set to get_option('prefix') / libexecdir / 'cinnamon-screensaver' for this.

That way, these would all be installed into a private directory like /usr/libexec/cinnamon-screensaver/ across all platforms.

At the moment, the packaging in debian/ overrides the libexec directory to be cinnamon-screensaver-specific (perhaps only as a result of historical debhelper defaults), but on e.g. Arch- or Red Hat-derived platforms these files would be installed directly into /usr/libexec, and I don't think that's what you really intend.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's somewhat conventional to define a variable like pkglibexecdir = libexecdir / 'cinnamon-screensaver', and then use things like install_dir: pkglibexecdir to reduce repetition.

src/binfile.in Outdated
@@ -5,4 +5,7 @@ if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
exit 1
fi

export GI_TYPELIB_PATH="@libexecdir@"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're installing the typelib as @libexecdir@/girepository-1.0/CScreensaver-1.0.typelib then you will need to use a path like @libexecdir@/girepository-1.0 here.

(Similarly if you add a .../cinnamon-screensaver/... path component as I suggest above, you'll need to take that into account here and in the LD_LIBRARY_PATH.)

It would be OK to put the typelib either in the same private directory as the .so, or in a girepository-1.0 subdirectory, but you'll need to choose one or the other and then be consistent about it.

@smcv
Copy link

smcv commented Jul 29, 2024

tried GIRepository.Repository.prepend_library_path

There are two search paths that are important for finding a typelib that describes a private library.

GObject-Introspection needs to be able to find the typelib. That's done by using the GI_TYPELIB_PATH environment variable, or the GIRepository.Repository.prepend_search_path function. You only need to use one or the other of those, not both, but you do need to give it the correct path to the directory that has the typelib in it (and if that directory has a /girepository-1.0 suffix then you will need to take that into account).

It also needs to be able to find the actual shared library. That's done by using the LD_LIBRARY_PATH environment variable, or the GIRepository.Repository.prepend_library_path function. Again, you only need to use one or the other of those, not both; this time you need to give it the path to the directory that has the shared library in it.

If your typelib and your shared library are both private, as they are in this PR, then you need to set up both search paths.

@mtwebster
Copy link
Member Author

Thanks, updated. I think I moved the typelib location (and didn't test it) just before opening this - it worked for me :)

@Fantu I'm not sure I can get rid of the dummy package though - I tried what you suggested (adding to cinnamon-screensaver's Breaks) but the install fails as it can't remove the old package.

If we just remove it without that Breaks, it installs fine, but you're still left with libcscreensaver (with its files in /usr/lib/x86_64-linux-gnu...)

@Fantu
Copy link
Contributor

Fantu commented Jul 30, 2024

@smcv big thanks for all the information and advices

@mtwebster the breaks should work and replaces/conflicts are not needed as file moved between the packages have different path. I tested it in Debian and worked (https://salsa.debian.org/cinnamon-team/cinnamon-screensaver/-/tree/experimental?ref_type=heads).

Breaks:
 libcscreensaver0 (<< ${source:Version}),

Used and worked also for other packages, previous time was for cinnamon-control-center-goa

Breaks:
 cinnamon-control-center-goa (<< ${source:Version}),

I did fast test on Debian unstable using debomatic as repository
6.2.0-1~ was previous test and cinnamon-screensaver 6.2.0-1~1 is the new with updated patches, did a fast test now and screensaver is working

There is only a minor thing spotted with lintian, library files are now executable (in previous build wasn't), probably is packaging that mark executable all files under /usr/libexec

E: cinnamon-screensaver: shared-library-is-executable 0755 [usr/libexec/cinnamon-screensaver/libcscreensaver.so]
W: cinnamon-screensaver: executable-not-elf-or-script [usr/libexec/cinnamon-screensaver/girepository-1.0/CScreensaver-1.0.typelib]

about these 2 lintian errors instead I think can be overrided as now we are using private libraries:

E: cinnamon-screensaver: custom-library-search-path RUNPATH /usr/libexec/cinnamon-screensaver [usr/libexec/cinnamon-screensaver/cinnamon-screensaver-pam-helper]
E: cinnamon-screensaver: custom-library-search-path RUNPATH /usr/libexec/cinnamon-screensaver [usr/libexec/cinnamon-screensaver/cs-backup-locker]

@smcv
Copy link

smcv commented Jul 30, 2024

library files are now executable (in previous build wasn't), probably is packaging that mark executable all files under /usr/libexec

This is a debhelper limitation (arguably a debhelper bug).

If you'd prefer to make the Debian packaging set the libexecdir to something like lib or lib/${DEB_HOST_MULTIARCH} (so that the private libraries and executables end up somewhere like /usr/lib/cinnamon-screensaver or /usr/lib/x86_64-linux-gnu/cinnamon-screensaver) then that would probably avoid this. Or the packaging could have an override_dh_fixperms which chmods the private library and typelib to 0644 rather than 0755.

about these 2 lintian errors instead I think can be overrided as now we are using private libraries

Yes. You're intentionally using private libraries via a DT_RUNPATH and that's fine; the lintian check is intended to catch situations where there's an unintentional use of DT_RUNPATH.

@Fantu
Copy link
Contributor

Fantu commented Jul 30, 2024

@smcv thanks for the information, I had just already done it after seeing from a quick search that the sudo package also has a similar situation, so I fixed the permissions and added the override as you also wrote.

https://salsa.debian.org/cinnamon-team/cinnamon-screensaver/-/commits/experimental
now seems all ok from a fast look
@mtwebster @clefebvre you think is now ok, and I'll push to Debian experimental for more testing, or you think more improvements are needed?

Probably also review of this PR from maintainers of other distro can be good, for example @leigh123linux

@leigh123linux leigh123linux self-requested a review July 30, 2024 14:31
Copy link
Contributor

@leigh123linux leigh123linux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes work ok on fedora.

@mtwebster
Copy link
Member Author

I honestly preferred this all in /usr/lib/**/cinnamon-screensaver - I guess I got the impression from this discussion that libexec was preferred by Debian - I'm ok with it here, and I suppose this makes transitioning away from the libcscreensaver0 package easier also.

@smcv
Copy link

smcv commented Jul 31, 2024

I honestly preferred this all in /usr/lib/**/cinnamon-screensaver - I guess I got the impression from this discussion that libexec was preferred by Debian

/usr/lib/*/cinnamon-screensaver would be fine too, but if you want to do that, then the upstream (Meson) part of the build system should be installing the private libraries and executables into libdir / 'cinnamon-screensaver' and not into libexecdir.

libexecdir being /usr/lib/*/cinnamon-screensaver is an outdated Debianism: in newer debhelper compat levels, it changes to /usr/libexec, the same as it would be in e.g. Fedora. Regardless of whether these private libraries are below libdir or libexecdir, I think they should be in a subdirectory rather than at top level. It's particularly bad for a private library to be directly inside the libdir.

The reason I suggested libexecdir / 'cinnamon-screensaver' was partly because this project was already using libexecdir in the upstream/Meson part of its build system, and partly because @Fantu was talking about potentially hard-coding the path into executable code (rather than using a template with @variables@ like you're now doing in this PR). If a path needs to be hard-coded somewhere for whatever reason, in my experience it's often simpler to achieve that if it's the same for all architectures (/usr/libexec/cinnamon-screensaver/whatever) rather than varying by architecture (/usr/lib/x86_64-linux-gnu/cinnamon-screensaver/whatever, /usr/lib/arm-linux-gnueabihf/cinnamon-screensaver/whatever and so on).

@Fantu
Copy link
Contributor

Fantu commented Jul 31, 2024

lib path arch based is required for multiarch support and probably also for shared library package (I don't remember good).
In this case with only one package without multiarch support and without shared library there are no obligations as far as I remember.
If I had to follow the first Debian maintainers (marga and maxy) who ported to /usr/lib/$(DEB_HOST_MULTIARCH) as much as possible I would do that, but lately I would like to try to do the same as upstream, if it doesn't go against some policy. If things are done in the best way I think it's better, but on several things I don't have enough knowledge to know exactly what is best.

@Fantu
Copy link
Contributor

Fantu commented Jul 31, 2024

I didn't see @smcv reply when writing, his reply gives useful information.
@smcv About hard-coded path I suppose you mean the fast tests I did try to have working initially, the improvement done after in this PR seems better also to me.

@mtwebster given the latest @smcv info where would you prefer to have between libdir and libexecdir?

@smcv
Copy link

smcv commented Jul 31, 2024

lib path arch based is required for multiarch support and probably also for shared library package (I don't remember good)

For public shared libraries like GLib or GTK, we always want to install below the architecture-specific ${libdir} so that you can install the 32- and 64-bit versions onto the same system if you find that you need both 32- and 64-bit programs to link to that library. It ends up in /usr/lib/*-linux-gnu on Debian/Ubuntu/Mint or /usr/lib{,64} on Fedora or /usr/lib{,32} on Arch.

For private shared libraries (like libcscreensaver becomes in this PR), that reasoning doesn't apply. You can't have both 32- and 64-bit cinnamon-screensaver installed anyway, because /usr/bin/cinnamon-screensaver can only be one or the other, not both; and it would be incorrect for anything outside the cinnamon-screensaver source tree to link to this library (that's what being a private library means). It would still be allowed to install into the ${libdir}, but it isn't required.

lately I would like to try to do the same as upstream, if it doesn't go against some policy

I think part of the confusion here is that this source tree contains both the upstream project (cinnamon-screensaver and its Meson build system), and a set of downstream packaging files for Mint (the debian/ directory); so there is sometimes a temptation to do things that, from an upstream point of view, are strange (like installing private app-internal files directly into libexecdir), because the debian/ directory in the same source tree happens to have compensated for them.

Comment on lines +8 to +9
export GI_TYPELIB_PATH="@typelibdir@"
export LD_LIBRARY_PATH="@pkglibdir@"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use

Suggested change
export GI_TYPELIB_PATH="@typelibdir@"
export LD_LIBRARY_PATH="@pkglibdir@"
export GI_TYPELIB_PATH="@typelibdir@${GI_TYPELIB_PATH:+:}$GI_TYPELIB_PATH"
export LD_LIBRARY_PATH="@pkglibdir@${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"

here? On NixOS we relies on e.g. GI_TYPELIB_PATH to discover the system libraries, it will be nice not to override the existing one (ref: GNOME/libsecret@2089893 and/or GNOME/gtk@29e6cc5). Without this the screensaver complains:

Traceback (most recent call last):
  File "/nix/store/acsigjq0ps6isqvy4jn37xmka7gw1psb-cinnamon-screensaver-6.2.0/share/cinnamon-screensaver/cinnamon-screensaver-main.py", line 4, in <module>
    gi.require_version('Gtk', '3.0')
  File "/nix/store/whykd0srhqzgfsxkkgbi1bx8yx9qdaz4-python3-3.12.4-env/lib/python3.12/site-packages/gi/__init__.py", line 122, in require_version
    raise ValueError('Namespace %s not available' % namespace)
ValueError: Namespace Gtk not available

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these just append to the standard path list? Why is this behavior different in NixOS?

Copy link
Contributor

@bobby285271 bobby285271 Aug 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same case on Guix 😂 On our side GOBJECT_INTROSPECTION_LIBDIR is a path like /nix/store/4cbm71y0q5r8i9r6jkx09vr22k55slsq-gobject-introspection-1.80.1/lib which is actually immutable and actually only contains typelibs from gobject-introspection. We have toolings to automatically wrap the program with the proper environment variables but that can't work if the program itself resets the env.

For example:

$ ls /nix/store/4cbm71y0q5r8i9r6jkx09vr22k55slsq-gobject-introspection-1.80.1/lib/girepository-1.0    
cairo-1.0.typelib  DBusGLib-1.0.typelib    freetype2-2.0.typelib     GL-1.0.typelib       Vulkan-1.0.typelib  xfixes-4.0.typelib  xlib-2.0.typelib
DBus-1.0.typelib   fontconfig-2.0.typelib  GIRepository-2.0.typelib  libxml2-2.0.typelib  win32-1.0.typelib   xft-2.0.typelib     xrandr-1.3.typelib

$ ls /nix/store/hrqbw86y0rid5qpxcy3s6sj97qgq23hb-xapp-2.8.5/lib/girepository-1.0                                                                                             
XApp-1.0.typelib

@Fantu
Copy link
Contributor

Fantu commented Aug 11, 2024

@mtwebster you want to do other changes or improvements to this PR? I want to use it on Debian, and I was wondering if I should wait any longer.
I also did a PR that include some packaging improvements that was already done in Debian: #459

@mtwebster
Copy link
Member Author

Sorry, I'll merge it today - are you certain I don't need a transitional package for libcscreensaver0?

@Fantu
Copy link
Contributor

Fantu commented Aug 13, 2024

On the PR I didn't added remove of the transitional package as you wrote didn't work:

@Fantu I'm not sure I can get rid of the dummy package though - I tried what you suggested (adding to cinnamon-screensaver's Breaks) but the install fails as it can't remove the old package.

I already tried in Debian and worked as it should and like other times I used it:

Package: cinnamon-screensaver
...
Breaks: libcscreensaver0 (<< ${source:Version})

obviously the version you install will have to be greater than the one installed for apt to do its job

on Debian I added also the breaks for remove gir1.2-cscreensaver-1.0 (that was created to solve policy issue with shared library package) and was worked also its remove

@Fantu
Copy link
Contributor

Fantu commented Aug 13, 2024

@mtwebster I did another look to documentation and should be correct the breaks (and only it as there is no file conflict in this case where the file path has changed)
See here for more details: https://www.debian.org/doc/debian-policy/ch-relationships.html#packages-which-break-other-packages-breaks

When one binary package declares that it breaks another, dpkg will refuse to allow the package which declares Breaks to be unpacked unless the broken package is deconfigured first, and it will refuse to allow the broken package to be reconfigured.

It occurred to me that maybe you didn't do a full test but a quick build on the same device (instead of building in clean environments) and tried to install the cinnamon-screensaver package directly with dpkg (instead of use a test repository, even a local one can do it if necessary) and so it should rightly fail because libcscreensaver0 is still installed and configured.
Is my guess correct?

@mtwebster
Copy link
Member Author

mtwebster commented Aug 13, 2024

Yes correct - just local installs with dpkg, though I was basing my initial assumptions on the guidelines here: https://wiki.debian.org/PackageTransition (Case 6)

I've bookmarked that new link, thanks.

mtwebster and others added 3 commits August 13, 2024 14:54
The cinnamon-screensaver package is already arch-specific, and
libcscreensaver isn't used outside of this package.

- Remove the libcscreensaver0 package.
- Move helpers and libcscreensaver to a /usr/libexec private folder.
- Clean up some variables, various build details.
There's really only one valid path, defined in the build.
@mtwebster mtwebster merged commit 0ad273f into master Aug 13, 2024
2 checks passed
@Fantu
Copy link
Contributor

Fantu commented Aug 13, 2024

The wiki page you linked is based on Debian Policy Manual page about declaring relationships between packages and have some useful examples. Debian Policy Manual is important and useful for packaging, I recommend you use it.
Merge a packaging in another keeping a transitional package is case 6 but as removed package is not a package installed by the user or other packages (build-depends/depends) transitional package is not needed, so can be case 11.
For fast check all packages in repository that depends on it can be useful apt-rdepends, if you don't already know it.
Anyway, with all files moved that changed also the path is different from the examples and don't need "Replaces" that is used when files overwriting files in other packages.
I hope I gave you useful information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants